package org.nViron.nvPlaces;

//~--- non-JDK imports --------------------------------------------------------

import java.util.ArrayList;
import java.util.Iterator;

import org.nViron.nvCommon.nvPosition;
import org.nViron.nvData.nvDataEntity;
import org.nViron.nvOrganic.nvOrganic;
import org.nViron.nvOrganism.nvOrganism;
import org.nViron.nvOrganism.nvStateMgr;
import org.nViron.nvRender.nvRenderer;

/**
 * A place is a specific location of interest where organics grow
 * @author Roland Haring <p>
 * <script type="text/javascript" src="http://www.ohloh.net/p/376434/widgets/project_basic_stats.js"></script>
 */
public class nvPlace extends nvOrganism {
    private nvOrganic  organic          = null;
    private ArrayList     entities         = new ArrayList();
    private nvPosition center           = new nvPosition();
    private ArrayList     previousOrganics = new ArrayList();

    public nvPlace(nvPlacesMgr placesMgr) {
        super(placesMgr);
        setState(nvStateMgr.SPROUTING);
    }

    public void addEntity(nvDataEntity entity, nvClusterer clusterer) {
        entities.add(entity);

        // calculate new center and update organic if required
        nvPosition newCenter = clusterer.getCenter(entities);

        if (organic == null) {
            center  = newCenter;
            organic = new nvOrganic(getPlaceMgr().getSimulator().getOrganicsMgr(), this);
            organic.sprout();
            organic.addEntity(entity);

            return;
        }

        if (!getPlaceMgr().getClusterer().keepCenter(center, newCenter)) {

            // let new organic sprout at new center and let old organic degenerate
            center = newCenter;

            nvOrganic newOrganic = new nvOrganic(getPlaceMgr().getSimulator().getOrganicsMgr(), this);

            newOrganic.setPosition(center);
            organic.degenerate();
            previousOrganics.add(organic);
            organic = newOrganic;

            for (Iterator it = entities.iterator(); it.hasNext(); ) {
                nvDataEntity prevEntity = (nvDataEntity) it.next();

                organic.addEntity(prevEntity);
            }

            organic.sprout();
        } else {

            // add entity to organic
            organic.addEntity(entity);
        }
    }

    @Override
    public void degenerate() {
        if (organic != null) {
            organic.degenerate();
        } else {
            setState(nvStateMgr.DEGENERATING);
        }
    }

    public nvPosition getCenter() {
        return center;
    }

    public ArrayList getEntities() {
        return entities;
    }

    public int getNumEntities() {
        return entities.size();
    }

    public nvPlacesMgr getPlaceMgr() {
        return (nvPlacesMgr) getObjectMgr();
    }

    public ArrayList getPreviousOrganics() {
        return previousOrganics;
    }

    public void removeEntity(nvDataEntity entity) {
        organic.removeEntity(entity);
    }

    public void render(nvRenderer renderer) {
        renderer.renderPlace(this);
    }

    @Override
    public void update(float timeStep) {
        super.update(timeStep);

        // update organics
        if (organic != null) {
            if (organic.getState() == nvStateMgr.DEAD) {
                organic = null;
                setState(nvStateMgr.DEAD);
            }
        }

        for (Iterator it = previousOrganics.iterator(); it.hasNext(); ) {
            nvOrganic prev = (nvOrganic) it.next();

            if (prev.getState() == nvStateMgr.DEAD) {
                prev.remove();
                it.remove();
            }
        }

        if (organic != null) {
            updateStateRelativeToChild(organic);
        }
    }
}



